home *** CD-ROM | disk | FTP | other *** search
/ PCGUIA 127 / PC Guia 127.iso / Software / Utils / Forecastfox / Bin / forecastfox-0.8.5.1-fx+mz+ns.xpi / components / ffParser.js < prev    next >
Encoding:
Text File  |  2006-02-18  |  17.8 KB  |  602 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Forecastfox.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Jon Stritar <jstritar@MIT.EDU>.
  18.  * Portions created by the Initial Developer are Copyright (C) 2005
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  * Jon Stritar <jstritar@MIT.EDU>
  23.  * Richard Klein <richwklein@mchsi.com>
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  27.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. const CLASS_ID = Components.ID("{CBD8A32B-0F47-4ac0-947D-D72E7ECB85F3}");
  40. const CLASS_NAME = "Forecastfox Parser Component";
  41. const CONTRACT_ID = "@ensolis.com/forecastfox/parser;1";
  42. const nsIDOMXPathResult = Components.interfaces.nsIDOMXPathResult;
  43. const ffIError = Components.interfaces.ffIError;
  44. const ffIDisk = Components.interfaces.ffIDisk;
  45.  
  46. /******************************************************************************
  47.  * ffParser Component
  48.  ******************************************************************************/
  49. function ffParser() {};
  50. ffParser.prototype = {
  51.   _xpath: null,
  52.   _xresolve: null,
  53.   _manager: null,  
  54.   _bundle: null,  
  55.   _data: null,
  56.   _targets: null,
  57.   _lists: null,
  58.   _masks: null,
  59.   
  60.   start: function()
  61.   {
  62.     var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
  63.     this._xpath = Components.classes["@mozilla.org/dom/xpath-evaluator;1"].getService(Components.interfaces.nsIDOMXPathEvaluator);
  64.     this._xresolve = Components.classes["@ensolis.com/forecastfox/resolver;1"].createInstance(Components.interfaces.nsIDOMXPathNSResolver);
  65.     this._manager = Components.classes["@ensolis.com/forecastfox/manager;1"].getService(Components.interfaces.ffIManager);
  66.     this._bundle = sbs.createBundle("chrome://forecastfox/locale/forecastfox.properties");
  67.     this._data = new Object();
  68.     this._loadParser();
  69.   },
  70.   
  71.   stop: function()
  72.   {
  73.     this._xpath = null;
  74.     this._xresolve = null;
  75.     this._manager = null;
  76.     this._bundle = null;
  77.     this._data = null;
  78.     this._targets = null;
  79.     this._lists = null;
  80.     this._masks = null;
  81.   },
  82.   
  83.   open: function(aDoc, aTarget, aNew)
  84.   {
  85.     //return error if parse doc not loaded      
  86.     if (!this._targets)
  87.       return this._createError(ffIError.SEVERITY_ERROR, "ff.parser.load", null, null);
  88.     
  89.     //do routine for new document
  90.     if (aNew) {
  91.  
  92.       //return error if aDoc not formed
  93.       if (!this._manager.disk.valid(aDoc))
  94.         return this._createError(ffIError.SEVERITY_ERROR, "ff.parser.formed", null, null);
  95.             
  96.       //check for error messages
  97.       this._build(aDoc, "error");
  98.       var message = this.getValue("error", "message", null);
  99.       if (message != "")
  100.         return this._createError(ffIError.SEVERITY_ERROR, null, message, message); 
  101.         
  102.       //check units
  103.       this._build(aDoc, "units"); 
  104.       if (this.getValue("units", "ut", null) == "")
  105.         return this._createError(ffIError.SEVERITY_ERROR, "ff.parser.units", null, null);
  106.     };
  107.       
  108.     //build target
  109.     this._build(aDoc, aTarget);
  110.     
  111.     //build includes
  112.     var target = this._targets[aTarget];
  113.     var data = new Object();   
  114.     for (var j=0; j<target.includes.length; j++) {
  115.       this._build(aDoc, target.includes[j]);
  116.       data = this._merge(data, this._data[target.includes[j]][0]);    
  117.     };
  118.         
  119.     //merge includes into each context
  120.     //only merge first context of the include
  121.     for (j=0; j<target.contexts.length; j++)
  122.       this._data[aTarget][j] = this._merge(data, this._data[aTarget][j]);       
  123.  
  124.           
  125.     //parser success return informational error
  126.     return this._createError(ffIError.SEVERITY_INFO, null, "", "");
  127.   },
  128.   
  129.   getItems: function(aTarget, aCount)
  130.   {
  131.     var items = new Array();
  132.     for (i in this._data[aTarget][0]) {
  133.       if (!this._data[aTarget][0][i].hidden)
  134.           items.push(i);
  135.     }
  136.  
  137.     aCount.value = items.length;       
  138.     return items;
  139.   },
  140.  
  141.   getDescription: function(aTarget, aItem)
  142.   {
  143.     //get the item    
  144.     var item = this._getItem(aTarget, aItem, 0); 
  145.     if (!item)
  146.       return "";
  147.     
  148.     return item.description;
  149.   },
  150.     
  151.   getValue: function(aTarget, aItem, aIndex)
  152.   {   
  153.     //get the item  
  154.     var item = this._getItem(aTarget, aItem, aIndex);   
  155.     if (!item)
  156.         return "";
  157.         
  158.     //no mask so just return value
  159.     if (item.mask == "" || item.value == "N/A")
  160.       return item.value;
  161.       
  162.     //return mask from converter
  163.     var mask = this._masks[item.mask];
  164.     if (mask) {
  165.       var units = this._manager.branch.getComplexValue("units.current", Components.interfaces.nsIPrefLocalizedString).data;
  166.       var conversion = this._manager.branch.getComplexValue("units." + item.mask + "." + units, Components.interfaces.nsIPrefLocalizedString).data;
  167.       return this.getConverter(item.mask, units, conversion, item.value);
  168.     };
  169.     
  170.     //not a named mask so return updated value
  171.     var val;
  172.     try {
  173.       mask = item.mask;    
  174.       mask = mask.replace("$VAL", "'" + String(item.value) + "'");
  175.       val = eval(mask);
  176.     } catch(e) {
  177.       val = item.value;
  178.     };
  179.       
  180.     return val; 
  181.   },
  182.  
  183.   getValueRaw: function(aTarget, aItem, aIndex)
  184.   {
  185.     //get the item
  186.     var item = this._getItem(aTarget, aItem, aIndex);
  187.             
  188.     //return the raw value
  189.     if (!item)
  190.       return null;
  191.  
  192.     return item.value;
  193.   },
  194.   
  195.   setLabel: function(aLabel, aTarget, aIndex)
  196.   {
  197.     var label = aLabel;
  198.     var comp = this;
  199.  
  200.     //XXX should come up with better solution than try/catch
  201.     try {
  202.       label = aLabel.replace(/\[[^\[\]]+\]/g, 
  203.         function (str) {
  204.           var item = str.substring(1, str.length-1);
  205.           if (comp._getItem(aTarget, item, aIndex))
  206.             return comp.getValue(aTarget, item, aIndex);
  207.           else
  208.             return str;
  209.         }
  210.       )
  211.     } catch (e) {};
  212.     return label;
  213.   },
  214.   
  215.   getConverters: function(aMask, aUnits, aCount)
  216.   {
  217.     var items = new Array();
  218.     var converters = this._masks[aMask][parseInt(aUnits)];
  219.     for (i in converters)
  220.       items.push(i);
  221.  
  222.     aCount.value = items.length;       
  223.     return items;
  224.   },
  225.   
  226.   getConverter: function(aMask, aUnits, aConverter, aValue)
  227.   {
  228.     //get the converter for that mask, unit, converter
  229.     var converter = this._masks[aMask][parseInt(aUnits)][aConverter];
  230.  
  231.     //replace value in calc 
  232.     var calc;
  233.     if (aValue != null)
  234.       calc = converter["calc"].replace("$VAL", aValue);
  235.     else
  236.       calc = "''";
  237.       
  238.     //replace calc with value
  239.     var val = converter["value"].replace("$CALC", calc);
  240.     return eval(val);     
  241.   },
  242.   
  243.   _getItem: function(aTarget, aItem, aIndex)
  244.   {
  245.     var data;
  246.     if (aIndex)
  247.       data = this._data[aTarget][aIndex];
  248.     else
  249.       data = this._data[aTarget][0];
  250.     
  251.     //item not found    
  252.     var item = data[aItem];   
  253.     if (!item)
  254.       return null;
  255.     else
  256.       return item; 
  257.   },
  258.     
  259.   _build: function(aDoc, aTarget)
  260.   {
  261.     var i, j, k, l;
  262.      
  263.     //build all with no document
  264.     if (!aTarget) {
  265.       for (i in this._targets)
  266.         this._build(aDoc, i);
  267.       return;
  268.     };
  269.     
  270.     //get the target we are building
  271.     var target = this._targets[aTarget];
  272.       
  273.     //do list based on context
  274.     this._data[aTarget] = new Array();
  275.     for (k=0; k<target.contexts.length; k++)
  276.       this._data[aTarget].push(this._buildList(aDoc, target.contexts[k], target.list));
  277.   },
  278.   
  279.   _buildList: function(aDoc, aContext, aList)
  280.   {
  281.     var list = this._lists[aList];
  282.     var data = new Object();
  283.     var context = (!aDoc || !aContext) ? null: this._evalPath(aDoc, aContext);
  284.     var i, item;
  285.     
  286.     //loop through items in list
  287.     for(i in list) {
  288.       item = this._buildItem(context, list[i]);
  289.       data[i] = item;
  290.     };
  291.     
  292.     return data;
  293.   },
  294.   
  295.   _buildItem: function(aContext, aItem)
  296.   {
  297.     var item = new Object();
  298.     item.description = aItem.description;
  299.     item.type = aItem.type;
  300.     item.hidden = aItem.hidden;
  301.     item.mask = aItem.mask;
  302.     
  303.     //no context so empty item
  304.     if (!aContext) {
  305.       item.value = this._setValue(null, item.type);
  306.       return item;
  307.     };
  308.     
  309.     //no path
  310.     var node, calc;
  311.     if (aItem.path == "")
  312.       item.value = this._setValue(null, item.type);
  313.     else {
  314.       //see if we have a calc
  315.       if (aItem.calc != "") {
  316.         node = this._evalPath(aContext, aItem.calc);
  317.         if (!node)
  318.           calc = aItem.path.replace("$CALC", "''");
  319.         else
  320.           calc = aItem.path.replace("$CALC", node.textContent);
  321.       } else
  322.         calc = aItem.path.replace("$CALC", "''");
  323.         
  324.       //try to resolve item path
  325.       node = this._evalPath(aContext, calc);
  326.       if (!node)
  327.         item.value = this._setValue(null, item.type);
  328.       else
  329.         item.value = this._setValue(node.textContent, item.type);
  330.     };
  331.      
  332.     return item;
  333.   },
  334.   
  335.   _setValue: function(aValue, aType)
  336.   {
  337.     var val = null;
  338.     switch(aType) {
  339.       case "string":
  340.       defaut:
  341.         val = (!aValue) ? "" : String(aValue);
  342.         break;
  343.       case "number":
  344.         val = (!aValue) ? 0 : Number(aValue);
  345.         if (aValue == "N/A")
  346.           val = "N/A";
  347.         break;
  348.       case "boolean":
  349.         val = (aValue == "true" || aValue == "1") ? true : false;
  350.         break;
  351.     };
  352.       
  353.     return val;
  354.   },
  355.   
  356.   _evalPath: function(aNode, aExpr)
  357.   {
  358.     var result = null;
  359.      
  360.     try {   
  361.       var results = this._xpath.evaluate(aExpr, aNode, this._xresolve, nsIDOMXPathResult.ANY_TYPE, null);
  362.       result = results.iterateNext(); 
  363.     } catch(e) {};
  364.     
  365.     return result;    
  366.   },
  367.     
  368.   _createError: function(aSeverity, aName, aDescription, aTooltip)
  369.   {
  370.     var description = (aName) ? this._bundle.GetStringFromName(aName + ".label") : aDescription;
  371.     var tooltip = (aName) ? this._bundle.GetStringFromName(aName + ".tooltip") : aTooltip;
  372.     var error = Components.classes["@ensolis.com/forecastfox/error;1"].createInstance(Components.interfaces.ffIError);
  373.     error.init(aSeverity, "@ensolis.com/forecastfox/parser;1", description, tooltip); 
  374.     return error;
  375.   },
  376.   
  377.   _createList: function(aList)
  378.   {
  379.     //make global list a new array
  380.     var name = aList.getAttribute("name");
  381.     this._lists[name] = new Object();
  382.     
  383.     //create each item that goes in list
  384.     for (var i=0; i<aList.childNodes.length; i++) {
  385.       if (aList.childNodes[i].localName != "item")
  386.         continue;
  387.     
  388.       this._createItem(name, aList.childNodes[i]);  
  389.     }
  390.   },
  391.   
  392.   _createTarget: function(aTarget)
  393.   {
  394.     //make global task an item
  395.     var name = aTarget.getAttribute("name");
  396.     this._targets[name] = new Object();
  397.     
  398.     //get the list
  399.     this._targets[name].list = aTarget.getAttribute("list");
  400.     
  401.     //get the context
  402.     var contexts = new Array();
  403.     var i;
  404.     for (i=0; i<aTarget.childNodes.length; i++) {
  405.       if (aTarget.childNodes[i].localName != "context")
  406.         continue;
  407.       contexts.push(aTarget.childNodes[i].getAttribute("path"));
  408.     };
  409.     
  410.     //get the includes
  411.     var includes = new Array();
  412.     for (i=0; i<aTarget.childNodes.length; i++) {
  413.       if (aTarget.childNodes[i].localName != "include")
  414.         continue;
  415.       includes.push(aTarget.childNodes[i].getAttribute("target"));
  416.     };
  417.      
  418.     this._targets[name].contexts = contexts;
  419.     this._targets[name].includes = includes;   
  420.   },
  421.   
  422.   _createItem: function(aList, aItem)
  423.   {
  424.     //create new item object
  425.     var item = new Object();
  426.     item.name = aItem.getAttribute("name");
  427.     item.type = aItem.getAttribute("type");
  428.     item.hidden = aItem.hasAttribute("hidden");
  429.     item.path = (aItem.hasAttribute("path")) ? aItem.getAttribute("path") : "";
  430.     item.value = this._setValue(null, item.type);
  431.     
  432.     //get description
  433.     try {
  434.       if (aItem.hasAttribute("alias"))  
  435.         item.description = this._bundle.GetStringFromName("ff.labels." + aItem.getAttribute("alias"));
  436.       else      
  437.         item.description = this._bundle.GetStringFromName("ff.labels." + item.name);
  438.     } catch(e) {
  439.       item.description = item.name;
  440.     }
  441.        
  442.     //get mask
  443.     if (aItem.hasAttribute("mask"))
  444.       item.mask = aItem.getAttribute("mask");
  445.     else
  446.       item.mask = "";
  447.     
  448.     //get calc
  449.     if (aItem.hasAttribute("calc"))
  450.       item.calc = aItem.getAttribute("calc");
  451.     else
  452.       item.calc = "";
  453.                   
  454.     this._lists[aList][item.name] = item;
  455.   },
  456.   
  457.   _loadParser: function()
  458.   {
  459.     //read file
  460.     var file = this._manager.disk.get("parser.xml", ffIDisk.TYPE_DEFAULTS);
  461.     if (!file.exists() || !file.isReadable())
  462.       return
  463.     var doc = this._manager.disk.read(file);
  464.     
  465.     //get target and list elements
  466.     var targets = doc.getElementsByTagName("target");
  467.     var lists = doc.getElementsByTagName("list");
  468.     var masks = doc.getElementsByTagName("mask");
  469.     
  470.     var i, j, k;    
  471.     if (targets.length == 0 || lists.length == 0 || masks == 0)
  472.       return;
  473.     
  474.     //create our masks
  475.     this._masks = new Object();
  476.     for (i=0; i<masks.length; i++) {
  477.       //create an array for the mask
  478.       var name = masks[i].getAttribute("name");
  479.       this._masks[name] = new Array();
  480.       
  481.       //get the different unit conversions
  482.       var conversions = masks[i].getElementsByTagName("conversion");
  483.       for (j=0; j<conversions.length; j++) {
  484.         var conversion = new Object();
  485.         
  486.         //get the converters for that unit
  487.         var converters = conversions[j].getElementsByTagName("converter");
  488.         for (k=0; k<converters.length; k++) {
  489.           var converter = converters[k].getAttribute("name");
  490.           conversion[converter] = new Object();
  491.           conversion[converter].calc = converters[k].getAttribute("calc");
  492.           conversion[converter].value = converters[k].getAttribute("value");
  493.         };
  494.       
  495.         //add the conversion to the mask array
  496.         this._masks[name].push(conversion);
  497.       };
  498.     };
  499.     
  500.     //create our lists and targets
  501.     this._lists = new Object();
  502.     this._targets = new Object();
  503.     
  504.  
  505.     for (i=0; i<lists.length; i++)
  506.       this._createList(lists[i]);
  507.     for (i=0; i<targets.length; i++)
  508.       this._createTarget(targets[i]);
  509.     
  510.     //do an empty build
  511.     this._build(null, null);        
  512.   },
  513.   
  514.   _merge: function(aObject1, aObject2)
  515.   {
  516.     var data = new Object();
  517.     
  518.     for (i in aObject2)
  519.       data[i] = aObject2[i];
  520.     
  521.     for (i in aObject1)
  522.       data[i] = aObject1[i];
  523.       
  524.     return data;
  525.   },
  526.      
  527.   ///////////////////////////
  528.   // nsIClassInfo  
  529.   getInterfaces: function(aCount)
  530.   {
  531.     var ifaces = new Array();
  532.     ifaces.push(Components.interfaces.ffIParser);
  533.     ifaces.push(Components.interfaces.nsIClassInfo);
  534.     ifaces.push(Components.interfaces.nsISupports);
  535.     aCount.value = ifaces.length;
  536.     return ifaces;
  537.   },
  538.   
  539.   getHelperForLanguage: function(aLanguage) { return null; },
  540.   get contractID() { return CONTRACT_ID; },
  541.   get classID() { return CLASS_ID; },
  542.   get classDescription() { return CLASS_NAME; },
  543.   get implementationLanguage() { return Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT; },
  544.   get flags() { return Components.interfaces.nsIClassInfo.SINGLETON; },
  545.          
  546.   ///////////////////////////
  547.   // nsISupports
  548.   QueryInterface: function (aIID)
  549.   {
  550.     if (!aIID.equals(Components.interfaces.ffIParser) &&
  551.         !aIID.equals(Components.interfaces.nsIClassInfo) &&      
  552.         !aIID.equals(Components.interfaces.nsISupports))
  553.       throw Components.results.NS_ERROR_NO_INTERFACE;
  554.     return this;
  555.   }
  556. };
  557.  
  558. /******************************************************************************
  559.  * XPCOM Functions for construction and registration
  560.  ******************************************************************************/
  561. var gModule = {
  562.   _firstTime: true,
  563.   registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
  564.   {
  565.     if (this._firstTime) {
  566.       this._firstTime = false;
  567.       throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
  568.     };
  569.     aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  570.     aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
  571.   },
  572.  
  573.   unregisterSelf: function(aCompMgr, aLocation, aType)
  574.   {
  575.     aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  576.     aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);        
  577.   },
  578.   
  579.   getClassObject: function(aCompMgr, aCID, aIID)
  580.   {
  581.     if (!aIID.equals(Components.interfaces.nsIFactory))
  582.       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  583.  
  584.     if (aCID.equals(CLASS_ID))
  585.       return gFactory;
  586.  
  587.     throw Components.results.NS_ERROR_NO_INTERFACE;
  588.   },
  589.  
  590.   canUnload: function(aCompMgr) { return true; }
  591. };
  592.  
  593. var gFactory = {
  594.   createInstance: function (aOuter, aIID)
  595.   {
  596.     if (aOuter != null)
  597.       throw Components.results.NS_ERROR_NO_AGGREGATION;
  598.     return (new ffParser()).QueryInterface(aIID);
  599.   }
  600. };
  601.  
  602. function NSGetModule(aCompMgr, aFileSpec) { return gModule; }